package drds.server.server;

import java.io.IOException;
import java.nio.channels.SocketChannel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import drds.server.Server;
import drds.server.config.ErrorCode;
import drds.server.config.model.Schema;
import drds.server.net.IO;
import drds.server.net.SessionContext$LifeCycle;
import drds.server.route.Route;
import drds.server.util.CurrentTimeMillis;

public class SessionContext extends SessionContext$LifeCycle {
	private static final Logger LOGGER = LoggerFactory.getLogger(SessionContext.class);
	private static final long AUTH_TIMEOUT = 15 * 1000L;

	private volatile boolean autoCommit;
	private volatile boolean transactionInterruptStatus;
	private volatile String transactionInterruptMessage = "";
	//
	private Session session;

	public SessionContext(SocketChannel socketChannel) throws IOException {
		super(socketChannel);
		this.autoCommit = true;
		this.transactionInterruptStatus = false;
	}

	@Override
	public boolean isIdleTimeout() {

		return CurrentTimeMillis.currentTimeMillis() > Math.max(lastWriteTime, lastReadTime) + AUTH_TIMEOUT;

	}

	public boolean isAutoCommit() {
		return autoCommit;
	}

	public void setAutoCommit(boolean autoCommit) {
		this.autoCommit = autoCommit;
	}

	private long lastInsertId;

	public long getLastInsertId() {
		return lastInsertId;
	}

	public void setLastInsertId(long lastInsertId) {
		this.lastInsertId = lastInsertId;
	}

	/**
	 * 设置是否需要中断当前事务
	 */
	public void setTransactionInterruptStatus(String transactionInterruptMessage) {
		if (!autoCommit && !transactionInterruptStatus) {
			transactionInterruptStatus = true;
			this.transactionInterruptMessage = transactionInterruptMessage;
		}
	}

	public boolean getTransactionInterruptStatus() {
		return transactionInterruptStatus;
	}

	public Session getSession() {
		return session;
	}

	public void setSession(Session session) {
		this.session = session;
	}

	public void execute(String sql, int type) {
		// 连接状态检查
		if (this.isClosed()) {
			LOGGER.error("ignore execute ,server connection is closed " + this);
			return;
		}
		// 事务状态检查
		if (transactionInterruptStatus) {
			writeErrorMessage(ErrorCode.ER_YES, "Transaction error, need to rollback." + transactionInterruptMessage);
			return;
		}

		Schema schema = Server.getInstance().getConfig().getSchema();
		routeAndExecute(sql, type, schema);

	}

	public Route route(String sql, int type) {

		Schema schema = Server.getInstance().getConfig().getSchema();
		if (schema == null) {
			writeErrorMessage(ErrorCode.ERR_BAD_LOGICDB, "DRDS数据库实例不存在");
			return null;
		}

		// 路由计算
		Route route = null;
		try {
			route = Server.getInstance().getRouterservice().route(Server.getInstance().getConfig().getDRDS(), schema, type, sql, "", this);

		} catch (Exception e) {
			StringBuilder s = new StringBuilder();
			LOGGER.error(s.append(this).append(sql).toString() + " err:" + e.toString(), e);
			String msg = e.getMessage();
			writeErrorMessage(ErrorCode.ER_PARSE_ERROR, msg == null ? e.getClass().getSimpleName() : msg);
			return null;
		}
		return route;
	}

	public void routeAndExecute(String sql, int type, Schema schema) {
		// 路由计算
		Route route = null;
		try {
			route = Server.getInstance().getRouterservice().route(Server.getInstance().getConfig().getDRDS(), schema, type, sql, "", this);

		} catch (Exception e) {
			StringBuilder s = new StringBuilder();
			LOGGER.error(s.append(this).append(sql).toString() + " err:" + e.toString(), e);
			String msg = e.getMessage();
			writeErrorMessage(ErrorCode.ER_PARSE_ERROR, msg == null ? e.getClass().getSimpleName() : msg);
			return;
		}
		if (route != null) {
			// session执行
			session.execute(route, type);
		}
	}

	/**
	 * 提交事务
	 */
	public void commit() {
		if (transactionInterruptStatus) {
			/**
			 * 如果出现事物终止,系统如何正确处理。
			 */
			writeErrorMessage(ErrorCode.ER_YES, "Transaction error, need to rollback.");
		} else {
			session.commit();
		}
	}

	/**
	 * 回滚事务
	 */
	public void rollback() {
		// 状态检查
		if (transactionInterruptStatus) {
			transactionInterruptStatus = false;
		}

		// 执行回滚
		session.rollBack();
	}

	/**
	 * 撤销执行中的语句
	 * 
	 * @param sessionContext
	 *            发起者为null表示是自己
	 */
	public void cancel(final SessionContext sessionContext) {
		processor.getExecutor().execute(new Runnable() {
			@Override
			public void run() {
				session.cancel(sessionContext);
			}
		});
	}

	@Override
	public void close(String reason) {
		super.close(reason);
		session.terminate();
	}

	public int getTransactionIsolationLevel() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void setIO() {
		// TODO Auto-generated method stub

	}

	@Override
	public IO getIO() {
		// TODO Auto-generated method stub
		return null;
	}

}
